home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 2
/
AACD 2.iso
/
AACD
/
Programming
/
fpc
/
compiler
/
link.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-09-24
|
16KB
|
540 lines
{
$Id: link.pas,v 1.2.2.4 1998/08/31 12:19:29 peter Exp $
Copyright (c) 1998 by the FPC development team
This unit handles the linker and binder calls for programs and
libraries
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
Unit link;
Interface
uses cobjects;
Type TLinker = Object
{ Internal variables. Don't access directly }
{$ifdef linux}
LinkToC : Boolean; { Should we link to the C libs? }
GccLibraryPath : String; { Where is GCCLIB ? }
DynamicLinker : String; { What Dynamic linker ? }
{$endif}
OFiles, LibFiles : TStringContainer;
Strip : Boolean; { Strip symbols ? }
MakeLib : Boolean; { If unit : Make library ?}
ExeName, { FileName of the exe to be created }
LibName : String; { FileName of the lib to be created }
LinkResName : String[32]; { Name of response file }
LinkOptions : String; { Additional options to the linker }
LibrarySearchPath : String; { Where to look for libraries }
{ Methods }
Constructor Init;
Procedure SetFileName(const s:string);
function FindObjectFile(s : string) : string;
Procedure AddLibraryFile(S : String);
Procedure AddObjectFile(S : String);
Function FindLinker : String; { Find linker, sets Name }
Function DoExec(const command,para:string):boolean;
Function WriteResponseFile : Boolean;
Function Link:boolean;
Procedure Make_Library;
end;
PLinker=^TLinker;
Var Linker : TLinker;
Implementation
uses
Script,globals,systems,dos,verbose;
Constructor TLinker.Init;
begin
OFiles.Init;
LibFiles.Init;
OFiles.Doubles:=False;
LibFiles.Doubles:=False;
Strip:=false;
LinkOptions:='';
LinkResName:='link.res';
ExeName:='';
LibName:='';
{$ifdef linux}
LinkToC:=False;
LibrarySearchPath:='';
DynamicLinker:='/lib/ld-linux.so.1';
{$endif}
end;
Procedure TLinker.SetFileName(const s:string);
var
path:dirstr;
name:namestr;
ext:extstr;
begin
FSplit(s,path,name,ext);
LibName:=Path+Name+target_info.DllExt;
ExeName:=Path+Name+target_info.ExeExt;
end;
var
LastLDBin : string;
Function TLinker.FindLinker:string;
var
ldfound : boolean;
begin
if LastLDBin='' then
begin
if (target_info.target=target_WIN32) then
{ the win32 linker has another name to allow cross compiling between }
{ DOS and Win32, I think it should be possible to compile an ld }
{ with handles coff and pe, but I don't know how (FK) }
LastLDBin:=FindExe('ldw',ldfound)
else
LastLDBin:=FindExe('amigald',ldfound);
if (not ldfound) and (not externlink) then
begin
Message1(exec_w_linker_not_found,LastLDBin);
externlink:=true;
end;
if ldfound then
Message1(exec_u_using_linker,LastLDBin);
end;
FindLinker:=LastLDBin;
end;
{ searches an object file }
function TLinker.FindObjectFile(s:string) : string;
var
found : boolean;
begin
if pos('.',s)=0 then
s:=s+target_info.objext;
s:=FixFileName(s);
if FileExists(s) then
begin
Findobjectfile:=s;
exit;
end;
findobjectfile:=search(s,'.;'+unitsearchpath+';'+exepath,found)+s;
if (not externasm) and (not found) then
Message1(exec_e_objfile_not_found,s);
end;
Procedure TLInker.AddObjectFile (S : String);
begin
if pos('.',s)=0 then
s:=s+target_info.objext;
s:=FixFileName(s);
OFiles.Insert (S);
end;
Procedure TLInker.AddLibraryFile(S:String);
begin
if pos('.',s)=0 then
s:=s+target_info.dllext;
LibFiles.Insert (S);
end;
Function TLinker.DoExec(const command,para:string):boolean;
begin
DoExec:=true;
if not externlink then
begin
swapvectors;
exec(command,para);
swapvectors;
if (dosexitcode<>0) then
begin
Message(exec_w_error_while_linking);
DoExec:=false;
exit;
end
else
if (dosError<>0) then
begin
Message(exec_w_cant_call_linker);
ExternLink:=true;
end;
end;
if externlink then
AsmRes.AddLinkCommand (Command,Para,ExeName);
end;
Function TLinker.WriteResponseFile : Boolean;
Var
LinkResponse : Text;
i : longint;
prtobj,s : string;
begin
{ Open linkresponse and write header }
assign(linkresponse,inputdir+LinkResName);
rewrite(linkresponse);
{ Write Header and set runtime object (prt0) }
case target_info.target of
target_WIN32 : begin
prtobj:='';
writeln(linkresponse,'INPUT (');
end;
target_PalmOS:
begin
prtobj:='';
end;
target_linux : begin
if cs_profile in aktswitches then
prtobj:='gprt0'
else
prtobj:='prt0';
{$ifdef Linux}
if LinkToC then
writeln(linkresponse,'SEARCH_DIR ('+GCCLibraryPath +')');
{$endif}
writeln(linkresponse,'INPUT (');
end;
target_AMIGA: begin
prtobj:='prt0';
writeln(linkresponse,'INPUT (');
end;
else
prtobj:='prt0';
end;
{ add objectfiles, start with prt0 always }
if prtobj<>'' then
Writeln(linkresponse,FindObjectFile(prtobj));
while not OFiles.Empty do
begin
s:=Findobjectfile(OFiles.Get);
if s<>'' then
Writeln(linkresponse,s);
end;
{ Write libraries like -l<lib> }
While not LibFiles.Empty do
begin
S:=LibFiles.Get;
i:=Pos(target_info.dllext,S);
if i>0 then
Delete(S,i,255);
Writeln (LinkResponse,'-l'+S);
end;
{ Write End of response file }
if target_info.target in [target_WIN32,target_linux,target_AMIGA] then
Writeln (LinkResponse,')');
{ Close response }
close(linkresponse);
WriteResponseFile:=True;
end;
Function TLinker.link:boolean;
var
bindbin : string[80];
bindfound : boolean;
_stacksize,i,
_heapsize : longint;
s,s2 : string[10];
dummy : file;
success : boolean;
begin
{$ifdef linux}
if LinkToC then
begin
AddObjectFile('/usr/lib/crt0.o');
AddObjectFile(FindObjectFile('lprt'));
AddLibraryFile('libc.a');
AddLibraryFile('libgcc.a');
end;
{$endif Linux}
{ Create Linkoptions }
case target_info.target of
target_GO32V1:
LinkOptions:=LinkOptions+' -oformat coff-go32';
target_GO32V2:
LinkOptions:=LinkOptions+' -oformat coff-go32-exe';
target_linux: begin
if cs_profile in aktswitches then
begin
AddLibraryFile('gmon');
AddLibraryFile('c');
end;
end;
end;
{$ifdef linux}
If not LibFiles.Empty then
LinkOptions:='-dynamic-linker='+DynamicLinker+' '+LinkOptions;
{$endif linux}
if Strip then
LinkOptions:=LinkOptions+' -s';
{ Write used files and libraries }
WriteResponseFile;
{ Call linker }
if not externlink then
Message1(exec_i_linking,ExeName);
{$ifdef linux}
success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' '+inputdir+LinkResName);
{$else}
if target_info.target in [target_WIN32,target_AMIGA] then
success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' '+inputdir+LinkResName)
else
success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' @'+inputdir+LinkResName);
{$endif}
{Bind}
if target_info.target=target_os2 then
begin
{Calculate the stack and heap size in kilobytes, rounded upwards.}
_stacksize:=(stacksize+1023) shr 10;
{Minimum stacksize for EMX is 32K.}
if _stacksize<32 then
_stacksize:=32;
str(_stacksize,s);
_heapsize:=(heapsize+1023) shr 10;
str(_heapsize,s2);
bindbin:=FindExe('emxbind',bindfound);
if (not bindfound) and (not externlink) then
begin
Message(exec_w_binder_not_found);
externlink:=true;
end;
DoExec(bindbin,'-k'+s+' -o '+exename+'.exe '+exename+' -aim -s'+s2);
end;
if (success) and (not externlink) then
begin
assign(dummy,LinkResName);
{$I-}
erase(dummy);
{$I+}
i:=ioresult;
end;
link:=success; { otherwise a recursive call to link method }
end;
Procedure TLinker.Make_Library;
{$ifndef linux}
var
arbin : string;
arfound : boolean;
{$endif}
begin
if cs_shared_lib in initswitches then
begin
WriteResponseFile;
{$ifdef linux}
DoExec(FindLinker,' -o '+libname+'.so -shared link.res');
{$else}
arbin:=FindExe('ar',arfound);
if (not arfound) and (not externlink) then
begin
Message(exec_w_ar_not_found);
externlink:=true;
end;
DoExec(arbin,'rs '+libname+'.a');
{$endif}
end;
end;
end.
{
$Log: link.pas,v $
Revision 1.2.2.4 1998/08/31 12:19:29 peter
* linux fixes
Revision 1.2.2.3 1998/08/18 13:44:49 carl
* Amiga LD was not called correctly
Revision 1.2.2.2 1998/08/13 17:41:23 florian
+ some stuff for the PalmOS added
Revision 1.2.2.1 1998/08/13 13:22:34 carl
+ Amiga target ld script
Revision 1.2 1998/03/30 09:50:49 michael
+ fix for library support.
Revision 1.1.1.1 1998/03/25 11:18:13 root
* Restored version
Revision 1.31 1998/03/13 22:45:58 florian
* small bug fixes applied
Revision 1.30 1998/03/11 22:22:52 florian
* Fixed circular unit uses, when the units are not in the current dir (from Peter)
* -i shows correct info, not <lf> anymore (from Peter)
* linking with shared libs works again (from Peter)
Revision 1.29 1998/03/10 16:27:39 pierre
* better line info in stabs debug
* symtabletype and lexlevel separated into two fields of tsymtable
+ ifdef MAKELIB for direct library output, not complete
+ ifdef CHAINPROCSYMS for overloaded seach across units, not fully
working
+ ifdef TESTFUNCRET for setting func result in underfunction, not
working
Revision 1.28 1998/03/10 01:17:19 peter
* all files have the same header
* messages are fully implemented, EXTDEBUG uses Comment()
+ AG... files for the Assembler generation
Revision 1.27 1998/03/05 22:43:47 florian
* some win32 support stuff added
Revision 1.26 1998/03/04 01:35:04 peter
* messages for unit-handling and assembler/linker
* the compiler compiles without -dGDB, but doesn't work yet
+ -vh for Hint
Revision 1.25 1998/03/02 01:48:42 peter
* renamed target_DOS to target_GO32V1
+ new verbose system, merged old errors and verbose units into one new
verbose.pas, so errors.pas is obsolete
Revision 1.24 1998/03/01 22:46:12 florian
+ some win95 linking stuff
* a couple of bugs fixed:
bug0055,bug0058,bug0059,bug0064,bug0072,bug0093,bug0095,bug0098
Revision 1.23 1998/02/28 03:56:15 carl
+ replaced target_info.short_name by target_info.target (a bit faster)
Revision 1.22 1998/02/26 11:57:09 daniel
* New assembler optimizations commented out, because of bugs.
* Use of dir-/name- and extstr.
Revision 1.21 1998/02/25 20:26:41 michael
+ fixed linking for linux
Revision 1.20 1998/02/24 14:20:53 peter
+ tstringcontainer.empty
* ld -T option restored for linux
* libraries are placed before the objectfiles in a .PPU file
* removed 'uses link' from files.pas
Revision 1.19 1998/02/23 02:54:23 carl
* bugfix of recusrive call to link
Revision 1.18 1998/02/22 23:03:18 peter
* renamed msource->mainsource and name->unitname
* optimized filename handling, filename is not seperate anymore with
path+name+ext, this saves stackspace and a lot of fsplit()'s
* recompiling of some units in libraries fixed
* shared libraries are working again
+ $LINKLIB <lib> to support automatic linking to libraries
+ libraries are saved/read from the ppufile, also allows more libraries
per ppufile
Revision 1.17 1998/02/19 00:11:00 peter
* fixed -g to work again
* fixed some typos with the scriptobject
Revision 1.16 1998/02/18 13:48:16 michael
+ Implemented an OS independent AsmRes object.
Revision 1.15 1998/02/18 08:55:26 michael
* Removed double declaration of LinkerOptions
Revision 1.14 1998/02/17 21:20:50 peter
+ Script unit
+ __EXIT is called again to exit a program
- target_info.link/assembler calls
* linking works again for dos
* optimized a few filehandling functions
* fixed stabs generation for procedures
Revision 1.13 1998/02/16 13:46:40 michael
+ Further integration of linker object:
- all options pertaining to linking go directly to linker object
- removed redundant variables/procedures, especially in OS_TARG...
Revision 1.12 1998/02/16 12:51:31 michael
+ Implemented linker object
Revision 1.11 1998/02/15 21:16:21 peter
* all assembler outputs supported by assemblerobject
* cleanup with assembleroutputs, better .ascii generation
* help_constructor/destructor are now added to the externals
- generation of asmresponse is not outputformat depended
Revision 1.10 1998/02/14 01:45:21 peter
* more fixes
- pmode target is removed
- search_as_ld is removed, this is done in the link.pas/assemble.pas
+ findexe() to search for an executable (linker,assembler,binder)
Revision 1.9 1998/02/13 22:26:28 peter
* fixed a few SigSegv's
* INIT$$ was not written for linux!
* assembling and linking works again for linux and dos
+ assembler object, only attasmi3 supported yet
* restore pp.pas with AddPath etc.
Revision 1.8 1998/02/13 10:35:09 daniel
* Made Motorola version compilable.
* Fixed optimizer
>>>>>>> h:/cvs/compiler/link.pas
Revision 1.7 1998/02/02 00:55:32 peter
* defdatei -> deffile and some german comments to english
* search() accepts : as seperater under linux
* search for ppc.cfg doesn't open a file (and let it open)
* reorganize the reading of parameters/file a bit
* all the PPC_ environments are now for all platforms
Revision 1.6 1998/02/01 15:02:11 florian
* swapvectors around exec inserted
Revision 1.5 1998/01/28 13:48:39 michael
+ Initial implementation for making libs from within FPC. Not tested, as compiler does not run
Revision 1.4 1998/01/25 18:45:43 peter
+ Search for as and ld at startup
+ source_info works the same as target_info
+ externlink allows only external linking
Revision 1.3 1998/01/24 00:36:07 florian
+ small fix to get it working with DOS (dynamiclinker isn't declared for dos)
Revision 1.2 1998/01/23 22:19:17 michael
+ Implemented setting of dynamic linker name (linux only).
Declared Make_library
-Fd switch sets linker (linux only)
* Reinstated -E option of Pierre
Revision 1.1 1998/01/23 17:57:41 michael
+ Initial implementation.
}